package autorization;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

/*--------------------- КЛАСС РОЛИ -------------------------*/
/**
 * Класс Роли. Экземпляры данного класса будут являться строками таблицы ролей.
 * Содержит в себе все аттрибуты, присущие отдельной роли:
 * идентификатор, наименование, приоритет, множество идентификаторов допустимых правил-действий
 * @author ID=1008, Ustinov Anton
 * @author ID=1001, Volk
 */
public class Role {

    static long IDCounter = 0;
    //Константы класса---------------
    /**
     * Стандартный приоритет
     */
    public static final long STANDART_PRIORITY = 0;
    //-------------------------------
    /* поля класса */
    private long ID;
    private String name;
    private SortedSet<LongComparable> AdmissibleActions = new TreeSet<LongComparable>();
    private long Prior;

    /* методы класса */

    /**
     * Конструктор роли
     * @param name - наименование создаваемой роли
     * В случае недопустимости указанного наименования
     * генерируется исключение NullPointerException
     */
    public Role(String name) throws NullPointerException {
        if ((name == null) || (name.equals(""))) {
            throw new NullPointerException();
        }
        ID = IDCounter++;
        this.name = name;
        Prior = 0;
    }

    /**
     * Добавление (разрешение) допустимого правила-действия для данной роли.
     * @param RuleID - уникальный идентификатор правила-действия
     */
    public synchronized boolean addAdmissibleAction(long RuleID) {
        if (!admissibleAction(RuleID)) {
            AdmissibleActions.add(new LongComparable(RuleID));
            return true;
        }else return false;
    }

    /**
     * Удаление (запрещение) допустимого правила-действия для данной роли.
     * @param RuleID - уникальный идентификатор правила-действия
     */
    public synchronized void removeAdmissibleAction(long RuleID) {
        if (admissibleAction(RuleID)) {
            AdmissibleActions.remove(new LongComparable(RuleID));
        } else {
            System.out.println("removeAdmissibleAction, Role:" + getName() + ": trying to remove non-existing action");
        }
    }

    /**
     * Проверка допустимости данного правила-действия для данного представителя класса Роли
     * @param RuleID - идентификатор правила-действия
     * @return true - если действие является допустимым, false в противном случае.
     */
    boolean admissibleAction(long RuleID) {
        return (AdmissibleActions.contains(new LongComparable(RuleID)));
    }

    /**
     * Получить идентификатор данной роли
     * @return идентификатор данной роли
     */
    public long getID() {
        return ID;
    }

    /**
     * Получить наименование данной роли
     * @return наименование данной роли
     */
    public String getName() {
        return name;
    }

    /**
     * Сохранение экземпляра данной роли в поток данных
     * @param Output - выходной поток данных
     * @throws java.io.IOException - в случае, если произойдёт ошибка ввода-вывода
     */
    public void saveToStream(DataOutputStream Output) throws IOException {
        Output.writeLong(ID);
        Output.writeUTF(name);
        Output.writeLong(Prior);
        Output.writeInt(AdmissibleActions.size());
        Iterator<LongComparable> iter = AdmissibleActions.iterator();
        LongComparable temp;
        while (iter.hasNext()) {
            temp = iter.next();
            Output.writeLong(temp.value);
        }
    }

    /**
     * Загрузка данных об экземпляре роли из входного потока
     * @param Input - входной поток
     * @throws java.io.IOException - в случае, если произойдёт ошибка ввода-вывода
     */
    public void loadFromStream(DataInputStream Input) throws IOException {
        ID = Input.readLong();
        name = Input.readUTF();
        Prior = Input.readLong();
        int size = Input.readInt();
        
        AdmissibleActions.clear();
        for (int i = 0; i < size; i++) {
            long value = Input.readLong();
            LongComparable temp = new LongComparable(value);
            AdmissibleActions.add(temp);
        }

    }

    /**
     * Получение приоритета данной Роли.
     * @return приоритет роли.
     */
    public long getPrior() {
        return Prior;
    }

    /**
     * Установка приоритета Роли, с учётом неотрицательности
     * @param val - новое значение приоритета
     * @return true - если приоритет был успешно обновлён,
     * false - если значение val - недопустимо
     */
    public boolean setPrior(long val) {
        if (val < 0) {
            return false;
        }
        this.Prior = val;
        return true;
    }

    /**
     * Получить итератор по множеству допустимых правил-действий
     * @return ссылка на итератор
     */
    public Iterator<LongComparable> getIterator() {
        return AdmissibleActions.iterator();
    }

    /**
     * Количество допустимых правил-действий для данной роли
     * @return Количество допустимых правил-действий для данной роли
     */
    public long actionsCount() {
        return AdmissibleActions.size();
    }

}